package org.lld.im.service.utils;

import com.alibaba.fastjson.JSONObject;
import com.lld.im.codec.proto.MessagePack;
import org.apache.commons.lang3.StringUtils;
import org.lld.im.common.constant.Constants;
import org.lld.im.common.enums.command.Command;
import org.lld.im.common.model.ClientInfo;
import org.lld.im.common.model.UserSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author: LunBoWang
 * @description: 给用户发送消息
 * @date: 2025/4/1 下午7:13
 * @version: 1.0
 */

@Component
public class MessageProducer {

    private static Logger logger = LoggerFactory.getLogger(MessageProducer.class);

    @Resource
    RabbitTemplate rabbitTemplate;

    @Resource
    UserSessionUtils userSessionUtils;

    private String queueName = Constants.RabbitConstants.MessageService2Im;

    public boolean sendMessage(UserSession session, Object msg) {
        try {
            logger.info("send message == {}", msg);
            rabbitTemplate.convertAndSend(queueName, session.getBrokerId().toString(), msg);
            return true;
        } catch (Exception e) {
            logger.error("send message error == {}", e.getMessage());
            return false;
        }
    }

    //包装数据，调用sendMessage
    public boolean sendPack(String toId, Command command, Object msg, UserSession userSession) {
        MessagePack messagePack = new MessagePack<>();
        //路由属性，发送给谁
        messagePack.setCommand(command.getCommand());
        messagePack.setToId(toId);
        messagePack.setClientType(userSession.getClientType());
        messagePack.setImei(userSession.getImei());
        messagePack.setAppId(userSession.getAppId());
        //添加发送的数据
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(msg));
        messagePack.setData(jsonObject);

        String body = JSONObject.toJSONString(messagePack);
        return sendMessage(userSession, body);
    }

    //发送给所有端的方法
    public List<ClientInfo> sendToUser(String toId, Command command, Object data, Integer appId) {
        List<UserSession> userSessions = userSessionUtils.getUserSessions(appId, toId);
        List<ClientInfo> list = new ArrayList<>();
        for (UserSession userSession : userSessions) {
            boolean b = sendPack(toId, command, data, userSession);
            if (b) {
                list.add(new ClientInfo(userSession.getAppId(), userSession.getClientType(), userSession.getImei()));
            }
        }
        return list;
    }

    public void sendToUser(String toId, Integer clientType, String imei,
                           Command command, Object data, Integer appId) {
        if (clientType != null && StringUtils.isNotBlank(imei)) {
            ClientInfo clientInfo = new ClientInfo(appId, clientType, imei);
            sendToUserExceptClient(toId, command, data, clientInfo);
        } else {
            sendToUser(toId, command, data, appId);
        }
    }

    //发送给某个用户的指定客户端
    public void sendToUser(String toId, Command command,
                           Object data, ClientInfo clientInfo) {
        UserSession userSession = userSessionUtils.getUserSession(clientInfo.getAppId(), toId,
                clientInfo.getClientType(), clientInfo.getImei());
        sendPack(toId, command, data, userSession);
    }

    //发送给除了某一端的其他端
    public void sendToUserExceptClient(String toId, Command command, Object data, ClientInfo clientInfo) {
        List<UserSession> userSessions = userSessionUtils.getUserSessions(clientInfo.getAppId(), toId);
        for (UserSession userSession : userSessions) {
            if (!isMatch(userSession, clientInfo)) {
                sendPack(toId, command, data, userSession);
            }
        }
    }

    private boolean isMatch(UserSession sessionDto, ClientInfo clientInfo) {
        return Objects.equals(sessionDto.getAppId(), clientInfo.getAppId())
                && Objects.equals(sessionDto.getClientType(), clientInfo.getClientType())
                && Objects.equals(sessionDto.getImei(), clientInfo.getImei());
    }
}